/**
 * Project:   dtu.fmes.googleloon.ui
 * File:      MainWindow.java
 * License: 
 *            This file is licensed under GNU General Public License version 3
 *            http://www.gnu.org/licenses/gpl-3.0.txt
 *
 * Copyright: Bartosz Cichecki [ cichecki.bartosz@gmail.com ]
 * Date:      Nov 20, 2013
 */

package dtu.fmes.loon.ui;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;

import javax.swing.JButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingConstants;
import javax.swing.UIManager;

import org.apache.log4j.Logger;

import dtu.fmes.loon.ui.components.PaintJPanel;
import dtu.fmes.loon.ui.listener.MainWindowListener;

/**
 * Main UI window
 * 
 * @author Bartosz Cichecki
 * 
 */
public class MainWindow {

	private static final Logger log = Logger.getLogger(MainWindow.class);

	private static final String GOOGLE_LOON_SIMULATOR_UI = "Google Loon Simulator UI";

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		} catch (Throwable e) {
			log.fatal(e.getMessage(), e);
		}

		EventQueue.invokeLater(new Runnable() {

			@Override
			public void run() {
				try {
					MainWindow window = new MainWindow();
					window.frmMain.setVisible(true);
				} catch (Exception e) {
					log.fatal(e.getMessage(), e);
				}
			}
		});
	}

	private final JFrame frmMain = new JFrame();

	private final JMenuBar menuBar = new JMenuBar();

	private final JMenu mnFile = new JMenu("File");

	private final JMenu mnSimulation = new JMenu("Simulation");

	private final JMenuItem mntmOpenSimulationResult = new JMenuItem("Open simulation result");

	private final JMenuItem mntmExit = new JMenuItem("Exit");

	private final JMenuItem mntmNextFrame = new JMenuItem("Next frame");

	private final JMenuItem mntmPreviousFrame = new JMenuItem("Previous frame");

	private final JMenuItem mntmBigStepNextFrame = new JMenuItem("Big step forward");

	private final JMenuItem mntmBigStepPreviousFrame = new JMenuItem("Big step backwards");

	private final JSeparator separator = new JSeparator();

	private final JMenuItem mntmZoomIn = new JMenuItem("Zoom in");

	private final JMenuItem mntmZoomOut = new JMenuItem("Zoom out");

	private final JPanel pnlControls = new JPanel();

	private final JSlider slider = new JSlider();

	private final JButton btnPrevious = new JButton("<");

	private final JButton btnNext = new JButton(">");

	private final JButton btnZoomOut = new JButton("-");

	private final JButton btnZoomIn = new JButton("+");

	private final JButton btnBigStepNextFrame = new JButton(">>");

	private final JButton btnBigStepPreviousFrame = new JButton("<<");

	private MainWindowListener mainWindowListener = new MainWindowListener(this);

	private final JScrollPane scrollableCanvas = new JScrollPane();

	private final PaintJPanel pnlCanvas = new PaintJPanel();

	private final JButton btnInfo = new JButton("Info");

	private final JSeparator separator2 = new JSeparator();

	private final JMenuItem mntmInfo = new JMenuItem("Info");

	private final InfoWindow infoFrame = new InfoWindow();

	private final JCheckBoxMenuItem chckbxmntmShowCoverageOnly = new JCheckBoxMenuItem("Show signal coverage only");

	private final JButton btnPlaystop = new JButton("Play");

	private final JTextField txtFldTime = new JTextField();

	/**
	 * Create the application.
	 */
	public MainWindow() {
		txtFldTime.setHorizontalAlignment(SwingConstants.RIGHT);
		txtFldTime.setEditable(false);
		txtFldTime.setColumns(10);
		initialize();
	}

	public JButton getBtnBigStepNextFrame() {
		return btnBigStepNextFrame;
	}

	public JButton getBtnBigStepPreviousFrame() {
		return btnBigStepPreviousFrame;
	}

	public JButton getBtnInfo() {
		return btnInfo;
	}

	public JButton getBtnNext() {
		return btnNext;
	}

	public JButton getBtnPlaystop() {
		return btnPlaystop;
	}

	public JButton getBtnPrevious() {
		return btnPrevious;
	}

	public JButton getBtnZoomIn() {
		return btnZoomIn;
	}

	public JButton getBtnZoomOut() {
		return btnZoomOut;
	}

	public JCheckBoxMenuItem getChckbxmntmShowCoverageOnly() {
		return chckbxmntmShowCoverageOnly;
	}

	public JFrame getFrmMain() {
		return frmMain;
	}

	public InfoWindow getInfoFrame() {
		return infoFrame;
	}

	public JMenuBar getMenuBar() {
		return menuBar;
	}

	public JMenu getMnFile() {
		return mnFile;
	}

	public JMenu getMnSimulation() {
		return mnSimulation;
	}

	public JMenuItem getMntmBigStepNextFrame() {
		return mntmBigStepNextFrame;
	}

	public JMenuItem getMntmBigStepPreviousFrame() {
		return mntmBigStepPreviousFrame;
	}

	public JMenuItem getMntmExit() {
		return mntmExit;
	}

	public JMenuItem getMntmInfo() {
		return mntmInfo;
	}

	public JMenuItem getMntmNextFrame() {
		return mntmNextFrame;
	}

	public JMenuItem getMntmOpenSimulationResult() {
		return mntmOpenSimulationResult;
	}

	public JMenuItem getMntmPreviousFrame() {
		return mntmPreviousFrame;
	}

	public JMenuItem getMntmZoomIn() {
		return mntmZoomIn;
	}

	public JMenuItem getMntmZoomOut() {
		return mntmZoomOut;
	}

	public PaintJPanel getPnlCanvas() {
		return pnlCanvas;
	}

	public JPanel getPnlControls() {
		return pnlControls;
	}

	public JScrollPane getScrollableCanvas() {
		return scrollableCanvas;
	}

	public JSeparator getSeparator() {
		return separator;
	}

	public JSlider getSlider() {
		return slider;
	}

	public JTextField getTxtFldTime() {
		return txtFldTime;
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		frmMain.setTitle(GOOGLE_LOON_SIMULATOR_UI);
		frmMain.setBounds(100, 100, 800, 450);
		frmMain.setMinimumSize(new Dimension(800, 450));
		frmMain.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frmMain.getContentPane().setLayout(new BorderLayout(0, 0));

		/*
		 * Menu
		 */

		frmMain.setJMenuBar(menuBar);

		/*
		 * File menu
		 */
		menuBar.add(mnFile);

		mntmOpenSimulationResult.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_MASK));
		mntmOpenSimulationResult.addActionListener(mainWindowListener);
		mnFile.add(mntmOpenSimulationResult);

		mntmExit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0));
		mntmExit.addActionListener(mainWindowListener);
		mnFile.add(mntmExit);
		mnSimulation.setEnabled(false);
		menuBar.add(mnSimulation);

		mntmNextFrame.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_KP_RIGHT, 0));
		mntmNextFrame.addActionListener(mainWindowListener);
		mnSimulation.add(mntmNextFrame);

		mntmPreviousFrame.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_KP_LEFT, 0));
		mntmPreviousFrame.addActionListener(mainWindowListener);
		mnSimulation.add(mntmPreviousFrame);

		mntmBigStepNextFrame.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_KP_RIGHT, InputEvent.ALT_MASK));
		mntmBigStepNextFrame.addActionListener(mainWindowListener);
		mnSimulation.add(mntmBigStepNextFrame);

		mntmBigStepPreviousFrame.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_KP_LEFT, InputEvent.ALT_MASK));
		mntmBigStepPreviousFrame.addActionListener(mainWindowListener);
		mnSimulation.add(mntmBigStepPreviousFrame);

		mnSimulation.add(separator);

		mntmZoomIn.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_ADD, 0));
		mntmBigStepPreviousFrame.addActionListener(mainWindowListener);
		mnSimulation.add(mntmZoomIn);

		mntmZoomOut.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_SUBTRACT, 0));
		mntmBigStepPreviousFrame.addActionListener(mainWindowListener);
		mnSimulation.add(mntmZoomOut);

		mnSimulation.add(separator2);

		mntmInfo.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_I, InputEvent.CTRL_MASK));
		mntmBigStepPreviousFrame.addActionListener(mainWindowListener);
		mnSimulation.add(mntmInfo);

		chckbxmntmShowCoverageOnly.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_MASK));
		chckbxmntmShowCoverageOnly.addActionListener(mainWindowListener);
		mnSimulation.add(chckbxmntmShowCoverageOnly);

		/*
		 * Canvas
		 */
		scrollableCanvas.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
		scrollableCanvas.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
		scrollableCanvas.getViewport().addChangeListener(mainWindowListener);

		frmMain.getContentPane().add(scrollableCanvas, BorderLayout.CENTER);

		scrollableCanvas.setViewportView(pnlCanvas);
		pnlCanvas.setLayout(null);
		pnlCanvas.addMouseMotionListener(mainWindowListener);
		frmMain.getContentPane().add(pnlControls, BorderLayout.SOUTH);
		pnlControls.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));

		btnPlaystop.setEnabled(false);
		btnPlaystop.addActionListener(mainWindowListener);
		pnlControls.add(btnPlaystop);

		btnBigStepPreviousFrame.setEnabled(false);
		btnBigStepPreviousFrame.addActionListener(mainWindowListener);
		pnlControls.add(btnBigStepPreviousFrame);

		btnPrevious.setEnabled(false);
		btnPrevious.addActionListener(mainWindowListener);
		pnlControls.add(btnPrevious);

		btnNext.setEnabled(false);
		btnNext.addActionListener(mainWindowListener);
		pnlControls.add(btnNext);

		btnBigStepNextFrame.setEnabled(false);
		btnBigStepNextFrame.addActionListener(mainWindowListener);
		pnlControls.add(btnBigStepNextFrame);

		slider.setEnabled(false);
		slider.setValue(0);
		slider.setMaximum(1);
		slider.addChangeListener(mainWindowListener);
		slider.addMouseWheelListener(mainWindowListener);
		pnlControls.add(slider);

		btnZoomOut.setEnabled(false);
		btnZoomOut.addActionListener(mainWindowListener);

		pnlControls.add(txtFldTime);
		pnlControls.add(btnZoomOut);

		btnZoomIn.setEnabled(false);
		btnZoomIn.addActionListener(mainWindowListener);
		pnlControls.add(btnZoomIn);

		btnInfo.setEnabled(false);
		btnInfo.addActionListener(mainWindowListener);
		pnlControls.add(btnInfo);
	}

	public void updateTitle(boolean keepOriginal, String name) {
		frmMain.setTitle((keepOriginal ? GOOGLE_LOON_SIMULATOR_UI : "") + " - " + name);
	}
}
